//
//  OvalLayer.swift
//  SBLoader
//
//  Created by Satraj Bambra on 2015-03-19.
//  Copyright (c) 2015 Satraj Bambra. All rights reserved.
//

import UIKit

class OvalLayer: CAShapeLayer {
  
  let animationDuration: CFTimeInterval = 0.3
  
  override init!() {
    super.init()
    fillColor = Colors.red.CGColor
    path = ovalPathSmall.CGPath
  }
  
  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
  
  var ovalPathSmall: UIBezierPath {
    return UIBezierPath(ovalInRect: CGRect(x: 50.0, y: 50.0, width: 0.0, height: 0.0))
  }
  
  var ovalPathLarge: UIBezierPath {
    return UIBezierPath(ovalInRect: CGRect(x: 2.5, y: 17.5, width: 95.0, height: 95.0))
  }
  
  var ovalPathSquishVertical: UIBezierPath {
    return UIBezierPath(ovalInRect: CGRect(x: 2.5, y: 20.0, width: 95.0, height: 90.0))
  }
  
  var ovalPathSquishHorizontal: UIBezierPath {
    return UIBezierPath(ovalInRect: CGRect(x: 5.0, y: 20.0, width: 90.0, height: 90.0))
  }
  
    
    /**
    你可以通过参考这个指导书来填充这些方法。所有其他的 *Layer （以layer结尾）的文件都用了相似的方式构建。
    
    注意：如果你想要学习更多的Bezier paths，那就检出我们系列指导书 Modern Core Graphics with Swift
    http://www.raywenderlich.com/90690/modern-core-graphics-with-swift-part-1
    */
  func expand() {
    
//    这个函数创建了一个 CABasicAnimation 的实例，这个实例用于改变椭圆从 ovalPathLarge.到 ovalPathSmall 的路径。启动项目为你提供了两者的Bezier paths。
    var expandAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path")
    expandAnimation.fromValue = ovalPathSmall.CGPath
    expandAnimation.toValue = ovalPathLarge.CGPath
    expandAnimation.duration = animationDuration
//    设置动画的 removedOnCompletion 的值为 false，fillMode 的值为 KCAFillModeForwards ，使得当动画结束的时候，椭圆保留它新的路径。
    expandAnimation.fillMode = kCAFillModeForwards
    expandAnimation.removedOnCompletion = false
    addAnimation(expandAnimation, forKey: nil)
  }
    /**
    使用视图中扩张的椭圆，下一步就是在椭圆的步调中设置一些反弹，使之摇摆起来
    1. 从大路径下降到被垂直压扁的动画
    
    2. 从垂直压扁变成水平和垂直都压扁
    
    3. 和垂直挤压（动画）切换
    
    4. 回到大路径结束动画
    
    5. 把你所有的动画合并到CAAnimationGroup组，并把这个动画组添加到你的 OvalLayout 中。
    
    每一个随后的动画的 beginTime 都是其前一个动画和动画持续时间的 beginTime 总和。你重复动画组两次就会给你一种摆动出稍微拉长的感觉
    */
  func wobble() {
    // 1
    var wobbleAnimation1: CABasicAnimation = CABasicAnimation(keyPath: "path")
    wobbleAnimation1.fromValue = ovalPathLarge.CGPath
    wobbleAnimation1.toValue = ovalPathSquishVertical.CGPath
    wobbleAnimation1.beginTime = 0.0
    wobbleAnimation1.duration = animationDuration

    // 2
    var wobbleAnimation2: CABasicAnimation = CABasicAnimation(keyPath: "path")
    wobbleAnimation2.fromValue = ovalPathSquishVertical.CGPath
    wobbleAnimation2.toValue = ovalPathSquishHorizontal.CGPath
    wobbleAnimation2.beginTime = wobbleAnimation1.beginTime + wobbleAnimation1.duration
    wobbleAnimation2.duration = animationDuration

    // 3
    var wobbleAnimation3: CABasicAnimation = CABasicAnimation(keyPath: "path")
    wobbleAnimation3.fromValue = ovalPathSquishHorizontal.CGPath
    wobbleAnimation3.toValue = ovalPathSquishVertical.CGPath
    wobbleAnimation3.beginTime = wobbleAnimation2.beginTime + wobbleAnimation2.duration
    wobbleAnimation3.duration = animationDuration

    // 4
    var wobbleAnimation4: CABasicAnimation = CABasicAnimation(keyPath: "path")
    wobbleAnimation4.fromValue = ovalPathSquishVertical.CGPath
    wobbleAnimation4.toValue = ovalPathLarge.CGPath
    wobbleAnimation4.beginTime = wobbleAnimation3.beginTime + wobbleAnimation3.duration
    wobbleAnimation4.duration = animationDuration

    // 5
    var wobbleAnimationGroup: CAAnimationGroup = CAAnimationGroup()
    wobbleAnimationGroup.animations = [wobbleAnimation1, wobbleAnimation2, wobbleAnimation3,
      wobbleAnimation4]
    wobbleAnimationGroup.duration = wobbleAnimation4.beginTime + wobbleAnimation4.duration
    wobbleAnimationGroup.repeatCount = 2
    addAnimation(wobbleAnimationGroup, forKey: nil)
  }
    /**
    这段代码应用 CABasicAnimation 类，将 OvalLayer 设置它的初始路径 ovalPathSmall。
    
    构建并运行你的应用程序，当动画完成的时候，只有三角形应该被留在屏幕上。
    */
  func contract() {
    var contractAnimation: CABasicAnimation = CABasicAnimation(keyPath: "path")
    contractAnimation.fromValue = ovalPathLarge.CGPath
    contractAnimation.toValue = ovalPathSmall.CGPath
    contractAnimation.duration = animationDuration
    contractAnimation.fillMode = kCAFillModeForwards
    contractAnimation.removedOnCompletion = false
    addAnimation(contractAnimation, forKey: nil)
  }
}
